home *** CD-ROM | disk | FTP | other *** search
- /*
- * FILECOPY.C
- *
- * (c)Copyright 1990,93 by Tobias Ferber, All Rights Reserved.
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include "filecopy.h"
-
- #ifdef AMIGA
- #include <exec/types.h>
- #include <exec/memory.h>
- #endif /* AMIGA */
-
- /* private statics */
- static uchar *copybuffer= (uchar *)0L;
- static ulong buffersize= 0L;
-
- static char rcs_id[]= "$Id: filecopy.c 1.2 93/09/19 21:33:11 tf Exp $";
-
- /*
- *
- * FUNCTION
- *
- * fc_setbuf -- allocate or free a copy buffer for filecopy()
- *
- * SYNOPSIS
- * #include "filecopy.h"
- *
- * result= fc_setbuf(numbytes)
- * ulong result;
- * ulong numbytes;
- *
- * DESCRIPTION
- *
- * This function tries to allocate 'numbytes' bytes for the local
- * copy buffer. If you pass 0L with the 'numbytes' parameter the
- * actual copy buffer will be free()d.
- * The current size of the copy buffer will be returned.
- *
- * NOTE
- *
- * It is absolutely legal to re-size your copy buffer by calling this
- * function only once (with your new buffer size) instead of calling
- * it twice (with numbytes==0L first)
- * Note also that this function does *NOT* check whether 'numbytes'
- * is larger than the local limit. (see "filecopy.h")
- *
- * SEE ALSO
- *
- * filecopy(), "filecopy.h"
- *
- */
-
- ulong fc_setbuf(numbytes)
- ulong numbytes;
- {
- #ifdef AMIGA
- if(copybuffer && buffersize)
- FreeMem(copybuffer, buffersize);
-
- #else /* !AMIGA */
- if(copybuffer)
- free(copybuffer);
-
- #endif /* AMIGA */
-
- copybuffer= (uchar *)0L;
- buffersize= 0L;
-
-
- if(numbytes)
- {
-
- #ifdef AMIGA
- copybuffer= (uchar *)AllocMem(numbytes*sizeof(uchar), MEMF_PUBLIC);
-
- #else /* !AMIGA */
- copybuffer= (uchar *)malloc(numbytes*sizeof(uchar));
-
- #endif /* AMIGA */
-
- if(copybuffer)
- buffersize= numbytes*sizeof(uchar);
- }
- return buffersize;
- }
-
- /*
- */
-
- #ifdef DEBUG
- /* My favorite way of reporting that we're alive: */
- static void turn(on)
- int on;
- {
- static char bars[]= "|/-\\|/-\\";
- static int b= 0;
-
- if(on)
- {
- fprintf(stderr,"%c\b",bars[b++]);
-
- if(b >= sizeof(bars)-1)
- b= 0;
- }
- else fprintf(stderr," \b");
-
- fflush(stderr);
- }
-
- #endif /* DEBUG */
-
-
- /*
- *
- * FUNCTION
- *
- * filecopy -- copy n bytes of data from one file pointer to another
- *
- * SYNOPSIS
- * #include "filecopy.h"
- *
- * result= filecopy(src, dst, n)
- * long result;
- * long n;
- * FILE *src, *dst;
- *
- * DESCRIPTION
- *
- * This function tries to copy 'n' bytes from given source stream 'src'
- * to the destination 'dst'.
- * If 'n' is == 0 then filecopy() will compute this value assuming that
- * all data following the current position of 'src' is ment to be copied.
- * If a copy buffer has been allocated successfully via fc_setbuf() then
- * filecopy() will take advantage of of it. On the other hand, if no
- * buffer was allocated it will do so on it's own and tries to get either
- * 'n' or (if 'n' is too large) MAXIMUM_BUFFERSIZE bytes. (See the notes
- * about this value in "filecopy.h".)
- * If the allocation fails then filecopy() will copy your data byte for
- * byte. Normally the number of written bytes will be returned but
- *
- * NOTE
- *
- * This function tries to be very careful concerning errors. If an error
- * occurs it will exit immediately returning either -1L in case of a read
- * error in the 'src' file or -2L in case of a write error with the 'dst'
- * file pointer.
- * Also filecopy() will *NOT* print out anything, even not if there was
- * an error. (There may of course be some output if your OS feels a need
- * to do so.) It's up to the caller to use perror() or sth. similar to
- * inform the user about what went wrong.
- *
- * NOTE ALSO
- *
- * This function assumes 'src' not to be a tty; especially not if you pass
- * n=0 with the arguments. In other words, filecopy() will fail if seeking
- * with 'src' is impossible.
- * You can however pass a value n<0 in order to force a byte for byte
- * transfer without seeking.
- *
- */
-
- long filecopy(src, dst, n)
- long n;
- FILE *src, *dst;
- {
- long result= 0L; /* The value returned by this function:
- * if non-negative the #of bytes written,
- * -1 = read error, -2 = write error */
-
- ulong remember= 0L; /* #of bytes allocated by *this* function */
- long bytesleft= 0L; /* #of bytes left for copying */
-
- if(n==0)
- {
- /* Compute the #of bytes left for copying */
-
- #ifdef BUGGY_FTELL
- do {
- (void)fgetc(src);
- if(!feof(src))
- ++bytesleft;
- } while(!feof(src) || ferror(src))
-
- #else /* ftell() works fine */
- if( fseek(src,0L,2L) >= 0) /* 2 == OFFSET_END */
- bytesleft= ftell(src);
- else
- result= -1L;
-
- #endif /* BUGGY_FTELL */
-
- if(!ferror(src) && bytesleft>0)
- { if(fseek(src,-bytesleft,1L) < 0) /* 1 == OFFSET_CURRENT */
- result= -1L;
- }
- else result= -1L;
- }
- else /* n!=0 */
- bytesleft= (n > 0) ? n : 0L;
-
-
- if(!result)
- {
- long nbytes= 0L;
-
- if(!copybuffer && bytesleft>0)
- {
- remember= fc_setbuf( (bytesleft > MAXIMUM_BUFFERSIZE) ?
- MAXIMUM_BUFFERSIZE : bytesleft );
- }
-
- /* If the allocation failed (or if n was negative) then we'll copy
- * the data byte for byte which of course is hyper slow ;)
- */
-
- if(!copybuffer || buffersize < 2L)
- {
- uchar c;
- int done= 0;
-
- do {
- c= fgetc(src);
- if(!feof(src))
- { fputc(c,dst);
- nbytes++;
- if(n>0 && nbytes>=n)
- done= 1;
- #ifdef DEBUG
- turn(1);
- #endif /* DEBUG */
- }
- } while(!done && !feof(src) && !ferror(src) && !ferror(dst));
-
- /* This might change later when checking ferror(): */
- result= nbytes;
- }
-
- else /* use the buffer */
- {
- long psize; /* packet size */
-
- do {
- psize= (bytesleft > buffersize) ? buffersize : bytesleft;
- bytesleft-= psize;
-
- /* I think it's a good idea to use fread() and fwrite() with
- * psize packets of size 1 here instead of 1 packet of size psize
- * because these functions return the number of *complete* packets
- * that were read (or written). This way we can also handle
- * partial packets if needed. */
-
- nbytes= fread(copybuffer, 1L, psize, src);
-
- if(!ferror(src))
- {
- /* write exactly as many bytes as we read before */
-
- nbytes= fwrite(copybuffer, 1L, nbytes, dst);
- result += nbytes;
- }
-
- /* A partial read or written packet indicates that we're done,
- * it does however not neccessarily mean that there was an error.
- * Changing the result to a negative value can be done later
- * by testing ferror(). */
-
- if(nbytes!=psize)
- bytesleft= 0;
-
- #ifdef DEBUG
- turn(1);
- #endif
-
- } while(bytesleft>0 && !ferror(src) && !ferror(dst));
- }
-
- if(ferror(src))
- result= -1L;
- else if(ferror(dst))
- result= -2L;
- }
-
- /* free the copy buffer if it was allocated by us */
- if(remember)
- fc_setbuf(0L);
-
- #ifdef DEBUG
- turn(0);
- #endif
-
- return result;
- }
-